package com.pktechan.api.controller;

import com.pktechan.api.base.wxPay.WXPayConstants;
import com.pktechan.api.base.wxPay.WXPayUtil;
import com.pktechan.api.dto.WxPayOrderReq;
import com.pktechan.api.dto.WxPayOrderResp;
import com.pktechan.api.entity.WxPayOrder;
import com.pktechan.api.enumeration.WxPayTradeStateEnum;
import com.pktechan.api.exception.CustomException;
import com.pktechan.api.service.TradeOrderService;
import com.pktechan.api.service.WxPayOrderService;
import com.pktechan.api.service.WxPayService;
import com.pktechan.api.utils.HtmlUtil;
import com.pktechan.api.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Map;

/**
 * @program: cloudfloating
 * @description: 微信支付控制器
 * @author: qx.zhang
 * @create: 2021-03-10 11:27
 **/
@RestController
@RequestMapping("wxPayController")
public class WxPayController {

    private static final Logger logger = LoggerFactory.getLogger(ProductController.class);

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private WxPayOrderService wxPayOrderService;
    @Autowired
    private TradeOrderService tradeOrderService;

    @Value("${wxpay.notify-url}")
    private String wxPayNotifyUrl;

    @Value("${wxpay.key}")
    private String wxPayKey;


    /**
     * 封装预下单方法
     *
     * @param request
     * @param response
     */
    @RequestMapping("/wxJSAPIPayOrder")
    public void wxJSAPIPayOrder(@RequestBody WxPayOrderReq wxPayOrderReq, HttpServletRequest request, HttpServletResponse response) {
        try {
            wxPayOrderReq.setSpbillCreateIp(request.getRemoteAddr());
            WxPayOrderResp wxPayOrderResp = wxPayOrderService.doUnifiedOrder(wxPayOrderReq);
            // 拼接并返回json
            HtmlUtil.writerSuccessJson(response, wxPayOrderResp);
        } catch (CustomException e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, "系统异常");
        }
    }

    /**
     * 根据订单ID查询微信支付预下单ID
     *
     * @param request
     * @param response
     */
    @RequestMapping("/getPrepayIdByTradeOrderId")
    public void getPrepayIdByTradeOrderId(@RequestBody WxPayOrderReq wxPayOrderReq, HttpServletRequest request, HttpServletResponse response) {
        try {
            wxPayOrderReq.setSpbillCreateIp(request.getRemoteAddr());
            WxPayOrderResp wxPayOrderResp = wxPayOrderService.getPrepayIdByTradeOrderId(wxPayOrderReq);
            // 拼接并返回json
            HtmlUtil.writerSuccessJson(response, wxPayOrderResp);
        } catch (CustomException e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, "系统异常");
        }
    }


    /**
     * 接收微信支付成功通知
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.debug("微信支付回调");
        PrintWriter writer = response.getWriter();
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        String result = new String(outSteam.toByteArray(), "utf-8");
        logger.debug("微信支付通知结果：" + result);
        Map<String, String> resultMap = null;
        try {
            resultMap = WXPayUtil.xmlToMap(result);
            boolean isSignatureValid = WXPayUtil.isSignatureValid(resultMap, wxPayKey, WXPayConstants.SignType.HMACSHA256);
            logger.info("isSignatureValid--------" + isSignatureValid);
            if (isSignatureValid) {
                // 若支付成功，则告知微信服务器收到通知
                if (resultMap.get("return_code").equals("SUCCESS")) {
                    //更新WxPayOrder
                    wxPayOrderService.updateWxPayOrder(resultMap);
                    String notifyStr = WXPayUtil.setXML("SUCCESS", "OK");
                    writer.write(notifyStr);
                    writer.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 接收微信退款结果通知
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/refundNotify")
    public void refundNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.debug("接收微信退款结果通知");
        PrintWriter writer = response.getWriter();
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        String result = new String(outSteam.toByteArray(), "utf-8");
        logger.debug("微信退款通知结果：" + result);
        Map<String, String> resultMap = null;
        try {
            resultMap = WXPayUtil.xmlToMap(result);

            // 若支付成功，则告知微信服务器收到通知
            if (resultMap.get("return_code").equals("SUCCESS")) {
                //TODO 处理订单
                WxPayOrder wxPayOrder = wxPayOrderService.getByOutTradeNo(resultMap.get("out_refund_no"));
                //校验金额是否一致
                if (wxPayOrder.getTotalFee().equals(Integer.parseInt(resultMap.get("total_fee")))) {
                    //更新WxPayOrder
                    wxPayOrderService.updateWxPayOrder(resultMap);
                    String notifyStr = WXPayUtil.setXML("SUCCESS", "OK");
                    writer.write(notifyStr);
                    writer.flush();
                } else {
                    String notifyStr = WXPayUtil.setXML("FAIL", "金额不匹配");
                    writer.write(notifyStr);
                    writer.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据业务系统代码与业务订单号码查询订单支付状态
     */
    @ResponseBody
    @RequestMapping(value = "/getWxPayOrderState", method = {RequestMethod.GET, RequestMethod.POST})
    public void getWxPayOrderState(String wxPayOutTradeNo, HttpServletRequest request, HttpServletResponse response) {
        String tradeState = "";
        try {
            WxPayOrder wxPayOrder = wxPayOrderService.getByOutTradeNo(wxPayOutTradeNo);
            tradeState = wxPayOrder.getTradeState();
            //订单状态为初始化时，查询微信服务器中的订单状态
            if (StringUtil.equals(WxPayTradeStateEnum.INITIAL.getCode(), tradeState)) {
                Map<String, String> respMap = wxPayService.doOrderQuery(wxPayOutTradeNo);
                //更新WxPayOrder
                wxPayOrderService.updateWxPayOrder(respMap);
                tradeState = respMap.get("trade_state");
            }
            HtmlUtil.writerSuccessJson(response, tradeState);
        } catch (CustomException e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, "系统异常");
        }
    }

    /**
     * 批量查询微信支付订单状态
     */
    @RequestMapping("/synWxPayOrderList")
    public void queryWxPayOrderList(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            wxPayOrderService.queryWxPayOrderList();
            HtmlUtil.writerSuccessJson(response, "同步完成");
        } catch (CustomException e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getMessage());
        }
    }

    /**
     * 申请退款
     */
    @RequestMapping("/refundWxPayOrder")
    public void refundWxPayOrder(String wxPayOutTradeNo, HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            wxPayOrderService.refundWxPayOrder(wxPayOutTradeNo);
            HtmlUtil.writerSuccessJson(response, "退款成功");
        } catch (CustomException e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getErrMsg());
        } catch (Exception e) {
            e.printStackTrace();
            HtmlUtil.writerFailJson(response, e.getMessage());
        }
    }
}
